package com.moyu.plugins.pokemsg.Listener;

import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import com.pixelmonmod.pixelmon.entities.pixelmon.EntityPixelmon;
import net.minecraft.server.v1_12_R1.BossBattle;
import net.minecraft.server.v1_12_R1.BossBattleServer;
import net.minecraft.server.v1_12_R1.PacketPlayOutBoss;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

//距离指示器
public class RangeDisplay {
	
	 final EntityPixelmon pokemon;
	private final BossBattle bar;
	private final SpawnListener sl;
	private final Set<Player> pUnVisible = new HashSet<>();//不可见玩家

	private int visible = 0;//-1显示结束，0未显示，1显示
	
	public RangeDisplay(EntityPixelmon pokemon, BossBattleServer bar, SpawnListener spawnListener){
		this.pokemon = pokemon;
		this.bar = bar;
		this.sl = spawnListener;
	}

	public void showOrDelay(){
		int time = sl.getConfig().getInt("LegendarySpawn.message.bossbar.delay");
		//若 延迟时间大于神兽刷新时间
		//延时显示
		//否则 直接显示
		if(20*time > pokemon.getBukkitEntity().getTicksLived())
		{
			new BukkitRunnable(){
				@Override
				public void run(){
					//是否被捉取消显示(显示结束)
					if (getVisible() != -1)
						show();
					this.cancel();
				}
			}.runTaskLaterAsynchronously(sl.getPlugin(),
					20*time - pokemon.getBukkitEntity().getTicksLived());
		}
		else {
			//是否被捉取消显示(显示结束)
			if (getVisible() != -1)
				show();
		}
	}


	//距离指示器显示计时
	private void show() {
		int stay = sl.getConfig().getInt("LegendarySpawn.message.bossbar.stay");
		//设为显示状态
		this.setVisible(1);
		//为同世界玩家显示
		for (Player p :
				Bukkit.getWorld(
						getEntity().getBukkitEntity().getWorld().getName()
				).getPlayers()
		)
			this.update(p);
		//发送指示器出现提示
		Bukkit.broadcastMessage(sl.bianLiang(
				sl.getConfig().getString("LegendarySpawn.message.bossbar.show_msg"),
				getEntity().getPokemonData().getDisplayName(),
				"",
				""
				)
		);

		//是否需要延时取消显示
		if(stay != 0)
			new BukkitRunnable(){
				@Override
				public void run(){
					//没有被其他事件取消显示
					if(getVisible() == 1) {
						setVisible(-1);
						remove();
//						sl.getPlugin().getLogger().info("神兽" + pokemon.getPokemonData().getDisplayName() + "指示器停留时间结束！");
					}
					this.cancel();
				}
			}.runTaskLaterAsynchronously(sl.getPlugin(), 20*stay);
	}

	//显示设置
	public void setVisible(int visible) {
		this.visible = visible;
	}
	
	//获取显示状态
	public int getVisible() {
		return visible;
	}

	//获取血条信息
	public BossBattle getBar() {
		return bar;
	}

	//获取神兽实体
	public EntityPixelmon getEntity() {
		if(!pokemon.getBukkitEntity().isDead())
			return pokemon;
		else
		{
			this.setVisible(-1);
			sl.getPlugin().getLogger().info("神兽" + pokemon.getPokemonData().getDisplayName() + "已消失、被捕或死亡！");
			remove();
			return null;
		}
	}

	//创建数据包
	private PacketContainer createPacketContainer() {
		BossBattle b = this.getBar();
		PacketContainer packet = new PacketContainer(PacketType.Play.Server.BOSS);
		//BossBattled的UUID写入数据包
		packet.getUUIDs().write(0, b.d());
		//颜色写入数据包
		packet.getSpecificModifier(b.color.getDeclaringClass()).write(0, b.color);
		//风格写入数据包
		packet.getSpecificModifier(b.style.getDeclaringClass()).write(0, b.style);
		return packet;
	}
	
	//设置距离
	public PacketContainer setRange(Player p) {
		//神兽未消失
		if(this.getEntity() == null) return null;
		//获取显示最大距离
		int maxlen = sl.getConfig().getInt("LegendarySpawn.message.bossbar.maxlen");
		//计算间距
		int range = sl.getRange(p.getLocation().getX(), getEntity().getBukkitEntity().getLocation().getX(),
				p.getLocation().getZ(), getEntity().getBukkitEntity().getLocation().getZ());

		PacketContainer packet = createPacketContainer();
		//数据包为更新操作
		packet.getSpecificModifier(PacketPlayOutBoss.Action.class).write(0, PacketPlayOutBoss.Action.ADD);

		//超过最大距离显示模式
		if(range > maxlen)
		{
			//设置标题内容
			packet.getChatComponents().write(
					0, 
					WrappedChatComponent.fromText(
					sl.bianLiang(
							sl.getConfig().getString("LegendarySpawn.message.bossbar.maxlen_title"),
							this.getEntity().getPokemonData().getDisplayName(), 
							"",
							Integer.toString(maxlen)
							))
					);
			//设置血条长度
			packet.getFloat().write(0, 1.0f);
		}
		//在最大距离内显示模式
		else
		{
			//设置标题
			packet.getChatComponents().write(
					0, 
					WrappedChatComponent.fromText(
					sl.bianLiang(
							sl.getConfig().getString("LegendarySpawn.message.bossbar.title"),
							this.getEntity().getPokemonData().getDisplayName(), 
							"",
							Integer.toString(range))
					));
			//设置血条长度
			packet.getFloat().write(0, range/(float)maxlen);
		}
		return packet;
	}


	//同世界显示数据包
	private void sendShowPacket(Player p) {
		//获取设置好间距的数据包
		PacketContainer packet = this.setRange(p);
		//若神兽消失结束执行
		if(packet == null) return;
		
		try {
			//发包
			sl.getPlugin().getPM().sendServerPacket(p, packet);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		
	}

	//发送结束显示数据包
	private void sendRemovePacket(Player p) {
		//获取数据包并设置为移除操作
		PacketContainer packet = createPacketContainer();
		packet.getSpecificModifier(PacketPlayOutBoss.Action.class).write(0, PacketPlayOutBoss.Action.REMOVE);

		try {
			sl.getPlugin().getPM().sendServerPacket(p, packet);
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	public void remove() {
		if(getVisible() == -1) {
			//为每人发包结束显示
			for (Player p:
					Bukkit.getOnlinePlayers())
				sendRemovePacket(p);
		}
	}
	
	public void update(Player p){
		if(getVisible() == 1) {
			//同世界
			if(p.getWorld().getName().equals(getEntity().getBukkitEntity().getWorld().getName()))
				this.sendShowPacket(p);//发包更新可见
			//不同世界且可见
			else if(!pUnVisible.contains(p)){
				//添加玩家到不可见列表
				pUnVisible.add(p);
				this.sendRemovePacket(p);//发包不可见
			}
		}
	}
}

